///<reference types="@i3yun/viewer" />
///<reference types="dat.gui" />
export class EventHandler {
    listeners = new Array<any>();
    dispatchEvent(data?: any) {
        this.listeners.forEach(_ => {
            _(data);
        })
    }
    addEventListener(value: any) {
        this.listeners.push(value);
    }
    removeEventListener(value: any) {
        let i = this.listeners.indexOf(value);
        if (i >= 0)
            this.listeners.splice(i, 1);
    }
}
export class HelperTool {
    static Clone<T>(value: T) {
        return JSON.parse(JSON.stringify(value)) as T;
    }
    static NameSpace(spaceName: string, space: any) {
        let all = window as any;
        all[spaceName] = space;
    }
    static getFullUrl(path: string, baseUrl?: string) {
        let keys = ["https://", "http://"];
        let rs = keys.findIndex(key => {
            return path.toLowerCase().startsWith(key.toLowerCase())
        }) >= 0;
        if (rs)
            return path;
        return baseUrl + path;
    }
    static loadCSS(url: string, root?: HTMLElement): Promise<HTMLLinkElement> {
        return new Promise<HTMLLinkElement>((resolve, reject) => {
            const script = document.createElement('link');
            script.rel = 'stylesheet';
            script.type = 'text/css';
            script.href = url;
            script.onload = () => resolve(script);
            script.onerror = () => reject(script);
            (root || document.head).appendChild(script);
        });
    }
    static loadScript(url: string, root?: HTMLElement): Promise<HTMLScriptElement> {
        return new Promise<HTMLScriptElement>((resolve, reject) => {
            const script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = url;
            script.onload = () => resolve(script);
            script.onerror = () => reject(script);
            (root || document.head).appendChild(script);
        });
    }
    static GetNull<T>(): T {
        return null as any as T;
    }
    static uuid() {
        var temp_url = URL.createObjectURL(new Blob());
        var uuid = temp_url.toString(); // blob:https://xxx.com/b250d159-e1b6-4a87-9002-885d90033be3
        URL.revokeObjectURL(temp_url);
        return uuid.substr(uuid.lastIndexOf("/") + 1);
    }
    static FromQuery(urlString?: string) {
        if (!urlString)
            urlString = window.location.toString();
        let url = new URL(urlString);
        var query = url.search.substring(1);
        var vars = query.split("&");
        var v: { [key: string]: string } = {};
        for (var i = 0; i < vars.length; i++) {
            var pair = vars[i].split("=");
            v[pair[0].toLowerCase()] = pair[1];
        }
        return v;
    }
    static httpGet(requestURL: string) {
        return new Promise((resolve, reject) => {
            //创建一个HTTP请求对象
            let request = new XMLHttpRequest();
            //使用open（）打开一个新请求
            request.open('GET', requestURL);
            //设置XHR访问JSON格式数据，然后发送请求
            request.send();

            //处理来自服务器的数据
            request.onload = function () {
                resolve(JSON.parse(request.response));
            };
            request.onerror = () => {
                reject(request);
            }
        });

    }
    static getRandomValue<T>(array: T[]) {
        return array[Math.round(array.length * Math.random())];
    }
    static Sum<T>(array: T[], countFun: (item: T) => number): number {
        let sum = 0;
        for (const item of array) {
            sum += countFun(item);
        }
        return sum;
    }
    static SelectMany<TSource, TResult>(queryable: TSource[], selector: (item: TSource) => TResult[]): TResult[] {
        var array = queryable;
        var a = new Array<TResult>();
        array.forEach(item => {
            a.push(...selector(item));
        })
        return a;
    }
    static stringToElement(content: string) {
        var el = document.createElement("div");
        el.innerHTML = content;
        return el.children[0] as HTMLElement;
    }
    static WaitTime(ms: number) {
        return new Promise<void>((s) => {
            setTimeout(() => {
                s();
            }, ms)
        })
    }
    static WaitTrue(func: () => boolean) {
        return new Promise<void>((s) => {
            let handle = setInterval(() => {
                if (func()) {
                    clearInterval(handle);
                    s();
                }
            }, 100)
        })
    }
    static WaitReturn<T>(func: () => { done: boolean, value?: T }) {
        return new Promise<T>((s) => {
            let handle = setInterval(() => {
                const rs = func();
                if (rs.done) {
                    clearInterval(handle);
                    s(rs.value as T);
                }
            }, 100)
        })
    }
    static ToThreeColor(guiColor: Array<number>) {
        return [255, 255, 255, 1].map((v, i) => {
            return guiColor[i] / v
        })
    }
    static ToGuiColor(threeColor: Array<number>) {
        return [255, 255, 255, 1].map((v, i) => {
            return threeColor[i] * v
        })
    }
}

